using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Tomahawk.Runtime.Screen.Controls;

namespace Tomahawk.Runtime.Screen.Controls
{
    /// <summary>
    /// This class represent a menu
    /// </summary>
    public class Menu : ScreenControl
    {

        List<MenuOption> options;
        int selectedOptionIndex = 0;

        private int barHeight;
        private int barWidth;
        private string barTextureAsset;
        private string barShaderAsset;

        private int optionSeparation;
        private string optionShaderAsset;
        private int optionWidth;
        private int optionHeight;

        private float barVelocity = 15.0f;
        private float firstOptionDepth = 0;

        private TexturedTile menuBar;

        private Color normalTextColor = Color.Ivory;

        private Color selectedTextColor = Color.HotPink;

        private bool useMenuBar = false;

        /// <summary>
        /// Constructor
        /// </summary>
        public Menu()
        {
            //this.optionShaderAsset = optionShaderAsset;
            this.options = new List<MenuOption>();
        }

        #region "Presentation public properties"

        /// <summary>
        /// Indicates if a background bar should be used to designate the selected option
        /// </summary>
        public bool UseMenuBar
        {
            get { return this.useMenuBar; }
            set { this.useMenuBar = value; }
        }

        /// <summary>
        /// Get or sets the default option height
        /// </summary>
        public int OptionSeparation
        {
            get { return optionSeparation; }
            set { optionSeparation = value; }
        }

        /// <summary>
        /// The shader that the options will be using
        /// </summary>
        public string OptionShaderAsset
        {
            get { return optionShaderAsset; }
            set { optionShaderAsset = value; }
        }

        /// <summary>
        /// The texture that the menu bar will be using
        /// </summary>
        public string BarTextureAsset
        {
            get { return barTextureAsset; }
            set { barTextureAsset = value; }
        }

        /// <summary>
        /// The shader that the menu bar will be using
        /// </summary>
        public string BarShaderAsset
        {
            get { return barShaderAsset; }
            set { barShaderAsset = value; }
        }

        public int OptionWidth
        {
            get { return optionWidth; }
            set { optionWidth = value; }
        }

        public int OptionHeight
        {
            get { return optionHeight; }
            set { optionHeight = value; }
        }

        public int BarHeight
        {
            get { return barHeight; }
            set { barHeight = value; }
        }

        public int BarWidth
        {
            get { return barWidth; }
            set { barWidth = value; }
        }

        #endregion

        /// <summary>
        /// Add a new menu option, it will place the option in its place
        /// </summary>
        /// <param name="normalTexture">The texture to use when the option is not selected</param>
        /// <param name="selectedTexture">The texture to use when the option is selected</param>
        public MenuOption AddMenuOption(string optionName, string caption)
        {
            //add the new option
            MenuOption opt = new MenuOption(optionName, caption, this.normalTextColor, this.selectedTextColor);
            options.Add(opt);

            //the first option added should appear selected
            if (options.Count == 1)
            {
                //if we have to display a menu bar then create it
                if (this.useMenuBar) addMenuBar();

                //the first option will be select as a default
                options[selectedOptionIndex].Selected = true;
            }

            //place the control / add child control
            opt.Y = (options.Count - 1) * this.optionSeparation;
            opt.X = 0;
            opt.Width = this.optionWidth;
            opt.Height = this.optionHeight;
            opt.DockMode = DockingModes.TopLeft;
            this.AddChildControl(opt);

            return opt;
        }

        /// <summary>
        /// Returns the selected option control
        /// </summary>
        public MenuOption SelectedOption
        {
            get { return this.options[this.selectedOptionIndex]; }
        }

        /// <summary>
        /// Select the next option
        /// </summary>
        public void SelectNextOption()
        {
            //deselect the current option
            this.options[this.selectedOptionIndex].Selected = false;
            //compute new index
            this.selectedOptionIndex++;
            if (this.selectedOptionIndex >= this.options.Count) this.selectedOptionIndex = 0;
            //select new option
            this.options[this.selectedOptionIndex].Selected = true;
        }

        /// <summary>
        /// Select the previous option
        /// </summary>
        public void SelectPreviousOption()
        {
            //deselect the current option
            this.options[this.selectedOptionIndex].Selected = false;
            //compute new index
            this.selectedOptionIndex--;
            if (this.selectedOptionIndex < 0) this.selectedOptionIndex = this.options.Count - 1;
            //select new option
            this.options[this.selectedOptionIndex].Selected = true;
        }

        /// <summary>
        /// Creates the menu background bar that designates the selected option
        /// </summary>
        private void addMenuBar()
        {
            //create the menu bar
            this.menuBar = new TexturedTile(this.barTextureAsset, this.barShaderAsset);
            this.menuBar.Width = this.barWidth;
            this.menuBar.Height = this.barHeight;
            this.menuBar.LayerDepth = this.firstOptionDepth + 0.0001f;
            this.AddChildControl(this.menuBar);
        }

        /// <summary>
        /// Animate the menu bar position
        /// </summary>
        public void UpdateBarPosition(float elapsedTime)
        {
            int destPos = this.selectedOptionIndex * this.optionSeparation;
            float inc = destPos - this.menuBar.Y;
            this.menuBar.Y = this.menuBar.Y + (inc * (elapsedTime * this.barVelocity));
        }

        /// <summary>
        /// Rendering (nothing special required)
        /// </summary>
        protected override void OnRender(GraphicsDevice device, SpriteBatch spriteBatch)
        {
        }

        /// <summary>
        /// Loading (nothing special required)
        /// </summary>
        protected override void OnLoadGraphicContent(GraphicsDevice myDevice, ContentManager myLoader)
        {
        }

    }

}


